<template>
  <li
    @mouseenter="hoverItem"
    @click.stop="selectOptionClick"
    class="el-select-dropdown__item"
    v-show="visible"
    :class="{
      selected: itemSelected,
      'is-disabled': disabled || groupDisabled || limitReached,
      hover: hover,
    }"
  >
    <slot>
      <span>{{ currentLabel }}</span>
    </slot>
  </li>
</template>

<script type="text/babel">
import Emitter from "element-ui/src/mixins/emitter";
import { getValueByPath, escapeRegexpString } from "element-ui/src/utils/util";

export default {
  mixins: [Emitter],

  name: "QmSelectOption",

  componentName: "QmSelectOption",

  inject: ["QmSelect"],

  props: {
    value: {
      required: true,
    },
    label: [String, Number],
    created: Boolean,
    disabled: {
      type: Boolean,
      default: false,
    },
  },

  data() {
    return {
      index: -1,
      groupDisabled: false,
      visible: true,
      hitState: false,
      hover: false,
    };
  },

  computed: {
    isObject() {
      return (
        Object.prototype.toString.call(this.value).toLowerCase() ===
        "[object object]"
      );
    },

    currentLabel() {
      return this.label || (this.isObject ? "" : this.value);
    },

    currentValue() {
      return this.value || this.label || "";
    },

    itemSelected() {
      if (!this.QmSelect.multiple) {
        return this.isEqual(this.value, this.QmSelect.value);
      } else {
        return this.contains(this.QmSelect.value, this.value);
      }
    },

    limitReached() {
      if (this.QmSelect.multiple) {
        return (
          !this.itemSelected &&
          (this.QmSelect.value || []).length >= this.QmSelect.multipleLimit &&
          this.QmSelect.multipleLimit > 0
        );
      } else {
        return false;
      }
    },
  },

  watch: {
    currentLabel() {
      if (!this.created && !this.QmSelect.remote)
        this.dispatch("QmSelect", "setSelected");
    },
    value(val, oldVal) {
      const { remote, valueKey } = this.QmSelect;
      if (!this.created && !remote) {
        if (
          valueKey &&
          typeof val === "object" &&
          typeof oldVal === "object" &&
          val[valueKey] === oldVal[valueKey]
        ) {
          return;
        }
        this.dispatch("QmSelect", "setSelected");
      }
    },
  },

  methods: {
    isEqual(a, b) {
      if (!this.isObject) {
        return a === b;
      } else {
        const valueKey = this.QmSelect.valueKey;
        return getValueByPath(a, valueKey) === getValueByPath(b, valueKey);
      }
    },

    contains(arr = [], target) {
      if (!this.isObject) {
        return arr && arr.indexOf(target) > -1;
      } else {
        const valueKey = this.QmSelect.valueKey;
        return (
          arr &&
          arr.some((item) => {
            return (
              getValueByPath(item, valueKey) ===
              getValueByPath(target, valueKey)
            );
          })
        );
      }
    },

    handleGroupDisabled(val) {
      this.groupDisabled = val;
    },

    hoverItem() {
      if (!this.disabled && !this.groupDisabled) {
        this.QmSelect.hoverIndex = this.QmSelect.options.indexOf(this);
      }
    },

    selectOptionClick() {
      if (this.disabled !== true && this.groupDisabled !== true) {
        this.dispatch("QmSelect", "handleOptionClick", [this, true]);
      }
    },

    queryChange(query) {
      this.visible =
        new RegExp(escapeRegexpString(query), "i").test(this.currentLabel) ||
        this.created;
      if (!this.visible) {
        this.QmSelect.filteredOptionsCount--;
      }
    },
  },

  created() {
    this.QmSelect.options.push(this);
    this.QmSelect.cachedOptions.push(this);
    this.QmSelect.optionsCount++;
    this.QmSelect.filteredOptionsCount++;

    this.$on("queryChange", this.queryChange);
    // this.$on("handleGroupDisabled", this.handleGroupDisabled);
  },

  beforeDestroy() {
    const { selected, multiple } = this.QmSelect;
    let selectedOptions = multiple ? selected : [selected];
    let index = this.QmSelect.cachedOptions.indexOf(this);
    let selectedIndex = selectedOptions.indexOf(this);

    // if option is not selected, remove it from cache
    if (index > -1 && selectedIndex < 0) {
      this.QmSelect.cachedOptions.splice(index, 1);
    }
    this.QmSelect.onOptionDestroy(this.QmSelect.options.indexOf(this));
  },
};
</script>
